#pragma once

#include <iostream>
#include <time.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdarg.h>
#include <fstream>
#include "LockGuard.hpp"
#include <pthread.h>


using namespace std;

bool gIsSave = true;
const char* logname = "log.txt";



enum Level
{
    DEBUG = 0,
    INFO,
    WARNING,
    ERROR,
    FATAL

};

string levelTostring(int level)
{
    switch (level)
    {
    case DEBUG:
        return "DEBUG";
    case INFO:
        return "INFO";
    case WARNING:
        return "WARNING";
    case FATAL:
        return "FATAL";
    default:
        return "UNKOWN";
    }
}

string TimeToString()
{
    time_t cur_time = time(nullptr);
    struct tm *tp = localtime(&cur_time);
    // 把数据都写到数组中
    char buffer[1024];
    snprintf(buffer, sizeof(buffer), "%d/%d/%d %d:%d:%d", tp->tm_year + 1900, tp->tm_mon + 1, tp->tm_mday, tp->tm_hour, tp->tm_min, tp->tm_sec);

    // 隐式类型转换
    return buffer;
}


void LogMessage(string filenamemm, int line, int issave, int level, const char *format, ...)
{
    string levelstr = levelTostring(level);
    string timestr = TimeToString();
    pid_t pid = getpid();


    char buffer[1024];
    va_list arg;
    va_start(arg,format);
    //将可变参数传入
    vsnprintf(buffer,sizeof(buffer),format,arg);
    va_end(arg);//把空间释放

    string message = "[" + timestr + "][" + levelstr + "]["
                      + to_string(pid) + "][" + filenamemm
                      + "][" + to_string(line) + "]" + buffer + "\n";

    //显示器是临界资源需要保护

    LockGuard();

    if(!issave)
        cout << message;
    else
    {
        ofstream out(logname,ios::app);
        if(!out.is_open())//如果文件打不开
        {
            return;
        }
        out<<message;
        out.close();
    }
}


#define EnableScreen() do{gIsSave = false;}while(0)

#define EnableFile() do{gIsSave = true;}while(0)

//c99新特性
#define Log(Level,format, ...) do{ LogMessage(__FILE__,__LINE__,gIsSave,Level,format,##__VA_ARGS__);}while(0)

